package com.czk.plugins;

import com.czk.pojo.Page;
import com.czk.utils.PageHelperUtils;
import com.czk.utils.UnsafeAccessor;
import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.springframework.core.annotation.Order;
import sun.misc.Unsafe;

import java.sql.Connection;

/**
 * 自定义分页插件
 * 分页插件与分表插件有冲突
 *
 * @Author:ChenZhangKun
 * @Date: 2021/4/20 11:19
 */
// @Component
@Order(3)
@Intercepts(@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}))
public class PageHelper implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 拿到代理对象
        RoutingStatementHandler routingStatementHandler = (RoutingStatementHandler) invocation.getTarget();
        // 拿到绑定的sql
        BoundSql boundSql = routingStatementHandler.getBoundSql();
        // 拿到sql
        String sql = boundSql.getSql();
        // 拿到分页参数
        Page page = PageHelperUtils.get();
        // 是否由分页参数
        if (page == null) {
            // 没有分页,放行
            return invocation.proceed();
        }
        // 瓶装sql
        Integer statPage = page.getStatPage();
        Integer pageSize = page.getPageSize();
        // 计算参数
        int currentPage = (statPage - 1) * pageSize;
        String newSql = sql + " limit " + currentPage + " , " + pageSize;
        // 拿到底层类
        Unsafe unsafe = UnsafeAccessor.getUnsafe();
        // 拿到偏移量
        long offset = unsafe.objectFieldOffset(boundSql.getClass().getDeclaredField("sql"));
        // 赋值
        unsafe.compareAndSwapObject(boundSql, offset, sql, newSql);
        // 移除，防止内存溢出
        PageHelperUtils.remove();
        return invocation.proceed();
    }
}
